#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <cerrno>
#include <poll.h>
#include "Socket.h"

#define FD_NONE -1

class Poll
{
public:
    //Poll() {}
    Poll(const uint16_t& port=8080)
    :_port(port)
    {
        _listensock=Sock().Socket();
        Sock().Bind(_listensock,_port);
        Sock().Listen(_listensock);

        _fds = new pollfd[_nfds];//申请对象
        for(int i=0;i<_nfds;i++)
        {
            _fds->fd=FD_NONE;
            _fds->events=0;
            _fds->events=0;
        }
        _fds[0].fd = _listensock;//初始化
        _fds[0].events = POLLIN;//读事件
        _timeout = 1000;//时间间隔
    }
    ~Poll()
    {
        if (_listensock >= 0)
            close(_listensock);
        if (_fds) delete [] _fds;
    }

    void Start()
    {
        while(true)
        {
            int n=poll(_fds,_nfds,_timeout);
            if(n<0)
            {
                logMessage(WARING,"poll fail:%d,%s",errno,strerror(errno));
                exit(1);
            }
            else if(n==0)
            {
                logMessage(DEBUG,"time out:%d,%s",errno,strerror(errno));
            }
            else
            {
                logMessage(DEBUG,"poll right:%d,%d",n,_listensock);
                HandlerEvent();
                break;
            }
        }
    }

private:
void HandlerEvent()
{
    for(int i=0;i<_nfds;i++)
    {
        if(_fds[i].fd==FD_NONE) continue;//去掉不合法的
        if(_fds[i].revents & POLLIN)
        {
            //指定的fd，读事件就绪
            // 读事件就绪：连接事件到来，accept
            if(_fds[i].fd == _listensock) Accept();
            else Recv(i);

        }
    }
}

void Accept()
{
    uint16_t clickport;
    std::string clickip;
    int sock=Sock().Accept(_listensock,&clickport,&clickip);
    if(sock<0)
    {
        logMessage(WARING,"accept fail,%d %s",errno,strerror(errno));
        exit(2);
    }
    logMessage(DEBUG,"accept right,%d",sock);
    int pos=1;
    for(;pos<_nfds;pos++)
    {
        if(_fds[pos].fd==FD_NONE) break;
    }
    if(pos==_nfds)
    {
        // 对struct pollfd进行自动扩容
        logMessage(WARING, "%s:%d", "poll server already full，close: %d", sock);
        close(sock);
    }
    else{
        _fds[pos].fd=sock;
        _fds[pos].events =POLLIN;
    }
}
void Recv(int pos)
{
    char buff[1024];
    int n=recv(_fds[pos].fd,buff,sizeof(buff)-1,0);
    if(n>0)
    {
        buff[n]=0;
        logMessage(DEBUG,"recv right:%s",n);
    }
    else if(n==0)
    {
        logMessage(DEBUG,"me too ,%s",n);
        close(_fds[pos].fd);
        _fds[pos].fd = FD_NONE;
        _fds[pos].events = 0;
    }
    else{
        logMessage(WARING, "%d sock recv error, %d : %s", _fds[pos].fd, errno, strerror(errno));
        close(_fds[pos].fd);
        _fds[pos].fd = FD_NONE;
        _fds[pos].events = 0;
        
    }
}
private:
    uint16_t _port;
    int _listensock;
    struct pollfd* _fds;
    int _nfds=100;
    int _timeout;
};